package tp;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.Random;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;

import tp.model.Train;
import tp.model.Trajet;
import tp.model.Ville;
import tp.util.DateTool;

/**
 * InsertData class for tp. This creates a simple product catalog, creates a
 * customer and order and amends the order.
 * 
 */
public class InsertData {

	public static void main(String[] args) {
		try {
			// load versant.properties project file as properties to connect
			Properties p = loadProperties();

			// run against local or remote Versant JDO Interface server
			PersistenceManagerFactory pmf = JDOHelper
					.getPersistenceManagerFactory(p);
			InsertData main = new InsertData(pmf.getPersistenceManager());
			try {
				main.go();
			} finally {
				main.pm.close();
			}
			System.exit(0);
		} catch (Exception e) {
			e.printStackTrace(System.out);
			System.exit(1);
		}
	}

	private static Properties loadProperties() throws IOException {
		Properties p = new Properties();
		InputStream in = null;
		try {
			in = InsertData.class.getResourceAsStream("/versant.properties");
			if (in == null) {
				throw new IOException("versant.properties not on classpath");
			}
			p.load(in);
		} finally {
			if (in != null)
				in.close();
		}
		return p;
	}

	private PersistenceManager pm;

	public InsertData(PersistenceManager pm) {
		this.pm = pm;
	}

	public void go() throws Exception {
		createVille();
		createTrain();
		createTrajet();

		showCatalog();
		String orderNo = createOrder();
		amendOrder(orderNo);
		complexQuery();
	}

	public void createTrajet() {
		pm.currentTransaction().begin();
		List<Ville> allVilles = findAllVille();
		Random r = new Random();

		Train t1 = findTrain("AB32");
		Train t2 = findTrain("CD98");

		Date now = new Date();
		for (int i = 0; i < 100; i++) {
			Train currentTrain = (i%2==0)?t1:t2;
			int r1 = r.nextInt(allVilles.size());
			int r2 = r.nextInt(allVilles.size());
			while (r2 == r1) {
				r2 = r.nextInt(allVilles.size());
			}

			Trajet trajet = new Trajet("t" + i, DateTool.ajouterJour(now, i),
					r.nextInt(500), allVilles.get(r1), allVilles.get(r2), currentTrain);
			pm.makePersistentAll(trajet);

		}
		pm.currentTransaction().commit();
	}

	/**
	 * Create the product catalog.
	 */
	private void createTrain() {
		pm.currentTransaction().begin();
		Train t = new Train("Jaqueline", "AB32", 112);
		Train t2 = new Train("George", "CD98", 230);
		pm.makePersistent(t);
		pm.makePersistent(t2);
		pm.currentTransaction().commit();
	}

	public Train findTrain(String modele) {
		Query q = pm.newQuery(Train.class);
		q.declareParameters("String m");
		q.setFilter("modele == m");
		q.setUnique(true);
		Train ans = null;
		try {
			ans = (Train) q.execute(modele);
			if (ans != null) {
				return ans;
			}
		} finally {
			if (ans != null)
				q.close(ans);
		}
		return null;

	}

	public List<Ville> findAllVille() {
		Query q = pm.newQuery(Ville.class);
		Collection<Ville> ans = (Collection<Ville>) q.execute();
		if (ans != null && !ans.isEmpty()) {
			List<Ville> res = new ArrayList<Ville>(ans);
			q.close(ans);
			return res;
		}
		return null;

	}

	public void createVille() {
		Ville nice = new Ville("Nice", "garde du nord");
		Ville paris = new Ville("Paris", "gare de Lyon");
		Ville marseille = new Ville("Marseille", "gare centrale");

		pm.currentTransaction().begin();
		pm.makePersistent(nice);
		pm.makePersistent(paris);
		pm.makePersistent(marseille);

		pm.currentTransaction().commit();
	}

	/**
	 * List all items in the catalog in description order.
	 */
	private void showCatalog() {
		// Query q = pm.newQuery(Item.class);
		// q.setOrdering("description ascending");
		// Collection ans = null;
		// try {
		// ans = (Collection)q.execute();
		// System.out.println("Catalog items in description order:");
		// for (Iterator i = ans.iterator(); i.hasNext();) {
		// Item item = (Item)i.next();
		// System.out.println(item.getCode() + ", " + item.getDescription() +
		// ", " + item.getCategory().getName());
		// }
		// System.out.println("---");
		// } finally {
		// if (ans != null) q.close(ans);
		// }
	}

	/**
	 * Find the item with code.
	 */
	// private Item lookupItem(String code) {
	// Query q = pm.newQuery(Item.class);
	// q.declareParameters("String c");
	// q.setFilter("code == c");
	// Collection ans = null;
	// try {
	// ans = (Collection)q.execute(code);
	// Iterator i = ans.iterator();
	// if (i.hasNext()) return (Item)i.next();
	// throw new IllegalArgumentException(
	// "No item with code: '" + code + "'");
	// } finally {
	// if (ans != null) q.close(ans);
	// }
	// return null;
	// }

	/**
	 * Create an order for a new customer and return the order number.
	 */
	private String createOrder() {
		// pm.currentTransaction().begin();
		// Order o = new Order(new Customer("DOE001", "John Doe"));
		// o.addLine(new OrderLine(lookupItem("D001"), 3));
		// o.addLine(new OrderLine(lookupItem("C001"), 1));
		// pm.makePersistent(o);
		// o = new Order(new Customer("DOE002", "Tom Smith"));
		// o.addLine(new OrderLine(lookupItem("D002"), 5));
		// o.addLine(new OrderLine(lookupItem("C001"), 2));
		// pm.makePersistent(o);
		// pm.currentTransaction().commit();
		// return pm.getObjectId(o).toString();
		return null;
	}

	/**
	 * Lookup the order and adjust all quantities to 1.
	 */
	private void amendOrder(String orderNo) {
		// pm.currentTransaction().begin();
		// Object oid = pm.newObjectIdInstance(Order.class, orderNo);
		// Order o = (Order)pm.getObjectById(oid, false);
		// for (Iterator i = o.getLines().iterator(); i.hasNext();) {
		// OrderLine ol = (OrderLine)i.next();
		// ol.setQty(1);
		// }
		// pm.currentTransaction().commit();
	}

	/**
	 * More complex query example.
	 */
	private void complexQuery() {
		// Query q = pm.newQuery(Order.class);
		// q.declareParameters("String c, int n, java.util.Date d");
		// q.declareVariables("OrderLine v");
		// q.setFilter(
		// "orderDate > d && lines.contains(v) && (v.item.code == c && v.qty > n)");
		// q.setOrdering("orderDate descending");
		// Calendar weekAgo = new GregorianCalendar();
		// weekAgo.add(Calendar.DAY_OF_YEAR, -7);
		// Collection ans = null;
		// try {
		// ans = (Collection)q.execute("D001", new Integer(5),
		// weekAgo.getTime());
		// System.out.println(
		// "Orders for Item D001 with qty > 5 placed in the last week:");
		// for (Iterator i = ans.iterator(); i.hasNext();) {
		// Order order = (Order)i.next();
		// System.out.println(order);
		// }
		// System.out.println("---");
		// } finally {
		// if (ans != null) q.close(ans);
		// }
	}

}
